package com.example.demo.service;

import com.example.demo.dto.TorrentResponse;
import com.example.demo.mapper.TorrentMapper;
import com.example.demo.mapper.TorrentSimilarityMapper;
import com.example.demo.mapper.UserBehaviorMapper;
import com.example.demo.mapper.UserInterestMapper;
import com.example.demo.model.Torrent;
import com.example.demo.model.UserBehavior;
import com.example.demo.model.UserInterest;
import com.example.demo.model.recommendation.TorrentSimilarity;
import com.example.demo.model.recommendation.UserSimilarity;
import com.example.demo.service.TorrentService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


// RecommendationService.java
// RecommendationService.java
@Service
@RequiredArgsConstructor
public class RecommendationService {
    @Autowired
    private final TorrentMapper torrentMapper;
    @Autowired
    private final UserBehaviorMapper userBehaviorMapper;
    @Autowired
    private final UserInterestMapper userInterestMapper;
    @Autowired
    private final TorrentService torrentService;
    @Autowired
    private final TorrentSimilarityMapper torrentSimilarityMapper;

    // 新增：计算并缓存用户相似度
    public void calculateUserSimilarities() {
        // 1. 获取用户-物品交互矩阵
        List<Map<String, Long>> matrix = userBehaviorMapper.getUserItemMatrix();

        // 2. 转换为用户-物品集合映射
        Map<Long, Set<Long>> userItemMap = new HashMap<>();
        for (Map<String, Long> row : matrix) {
            Long userId = row.get("user_id");
            Long torrentId = row.get("torrent_id");
            userItemMap.computeIfAbsent(userId, k -> new HashSet<>()).add(torrentId);
        }

        // 3. 计算用户相似度（余弦相似度）
        List<UserSimilarity> similarities = new ArrayList<>();
        List<Long> userIds = new ArrayList<>(userItemMap.keySet());

        for (int i = 0; i < userIds.size(); i++) {
            Long userId1 = userIds.get(i);
            Set<Long> items1 = userItemMap.get(userId1);

            for (int j = i + 1; j < userIds.size(); j++) {
                Long userId2 = userIds.get(j);
                Set<Long> items2 = userItemMap.get(userId2);

                // 计算交集
                Set<Long> intersection = new HashSet<>(items1);
                intersection.retainAll(items2);

                // 计算相似度
                double similarity = intersection.size() /
                        Math.sqrt(items1.size() * items2.size());

                if (similarity > 0.1) { // 过滤低相似度

                    UserSimilarity userSimilarity = new UserSimilarity();
                    userSimilarity.setUserId1(userId1);
                    userSimilarity.setUserId2(userId2);
                    userSimilarity.setSimilarity(similarity);

                    similarities.add(userSimilarity);
                }
            }
        }

        // 4. 批量存储到数据库（实际项目可考虑Redis缓存）
        // 这里简化处理，实际需要实现批量插入
        for (UserSimilarity similarity : similarities) {
            torrentSimilarityMapper.upsertUserSimilarity(similarity);
        }
    }

    // 新增：计算并缓存种子相似度
    public void calculateTorrentSimilarities() {
        // 1. 获取用户-物品交互矩阵
        List<Map<String, Long>> matrix = userBehaviorMapper.getUserItemMatrix();

        // 2. 转换为物品-用户集合映射
        Map<Long, Set<Long>> itemUserMap = new HashMap<>();
        for (Map<String, Long> row : matrix) {
            Long userId = row.get("user_id");
            Long torrentId = row.get("torrent_id");
            itemUserMap.computeIfAbsent(torrentId, k -> new HashSet<>()).add(userId);
        }

        // 3. 计算物品相似度（Jaccard相似度）
        List<TorrentSimilarity> similarities = new ArrayList<>();
        List<Long> torrentIds = new ArrayList<>(itemUserMap.keySet());

        for (int i = 0; i < torrentIds.size(); i++) {
            Long torrentId1 = torrentIds.get(i);
            Set<Long> users1 = itemUserMap.get(torrentId1);

            for (int j = i + 1; j < torrentIds.size(); j++) {
                Long torrentId2 = torrentIds.get(j);
                Set<Long> users2 = itemUserMap.get(torrentId2);

                // 计算交集和并集
                Set<Long> intersection = new HashSet<>(users1);
                intersection.retainAll(users2);

                Set<Long> union = new HashSet<>(users1);
                union.addAll(users2);

                // 计算相似度
                double similarity = (double) intersection.size() / union.size();

                if (similarity > 0.1) { // 过滤低相似度
                    TorrentSimilarity similarityRecord = new TorrentSimilarity();
                    similarityRecord.setTorrentId1(torrentId1);
                    similarityRecord.setTorrentId2(torrentId2);
                    similarityRecord.setSimilarity(similarity);
                    similarities.add(similarityRecord);
                }
            }
        }

        // 4. 批量存储到数据库
        for (TorrentSimilarity similarity : similarities) {
            torrentSimilarityMapper.upsertSimilarity(similarity);
        }
    }

    // 基于协同过滤的用户推荐
    public List<TorrentResponse> recommendByUserCF(Long userId) {
        List<Torrent> torrents = recommendByUserCFInternal(userId);
        return torrents.stream()
                .map(torrent -> {
                    String coverImageBase64 = null; // 默认为空
                    if (torrent.getCoverImage() != null) {
                        // 如果封面图片路径不为空，则进行转换
                        coverImageBase64 = torrentService.convertImageToBase64(torrent.getCoverImage());
                    }
                    return new TorrentResponse(torrent, coverImageBase64);
                })
                .collect(Collectors.toList());
    }

    private List<Torrent> recommendByUserCFInternal(Long userId) {
        // 获取相似用户
        List<UserSimilarity> similarities = userBehaviorMapper.findSimilaritiesByUser(userId);

        // 获取当前用户的行为记录
        Set<Long> userTorrents = userBehaviorMapper.findByUserId(userId).stream()
                .map(UserBehavior::getTorrentId)
                .collect(Collectors.toSet());

        // 收集相似用户喜欢的种子
        Map<Long, Double> candidateTorrents = new HashMap<>();
        for (UserSimilarity similarity : similarities) {
            Long similarUserId = similarity.getUserId1().equals(userId) ?
                    similarity.getUserId2() : similarity.getUserId1();

            List<UserBehavior> behaviors = userBehaviorMapper.findByUserId(similarUserId);
            for (UserBehavior behavior : behaviors) {
                Long torrentId = behavior.getTorrentId();
                if (!userTorrents.contains(torrentId)) {
                    candidateTorrents.put(torrentId,
                            candidateTorrents.getOrDefault(torrentId, 0.0) + similarity.getSimilarity());
                }
            }
        }

        // 按相似度排序并获取种子详情
        return candidateTorrents.entrySet().stream()
                .sorted(Map.Entry.<Long, Double>comparingByValue().reversed())
                .limit(20)
                .map(entry -> torrentService.getTorrentById(entry.getKey()))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }
    public List<TorrentResponse> recommendRelatedTorrentsCF(String infoHash) {
        List<Torrent> torrents = recommendRelatedTorrentsCFInternal(infoHash);
        return torrents.stream()
                .map(torrent -> {
                    String coverImageBase64 = null;
                    if (torrent.getCoverImage() != null) {
                        coverImageBase64 = torrentService.convertImageToBase64(torrent.getCoverImage());
                    }
                    return new TorrentResponse(torrent, coverImageBase64);
                })
                .collect(Collectors.toList());
    }

    private List<Torrent> recommendRelatedTorrentsCFInternal(String infoHash) {
        Torrent current = torrentService.getTorrentByHash(infoHash);
        if (current == null) return Collections.emptyList();

        List<Map<String, Object>> similarTorrents = torrentSimilarityMapper
                .findSimilarTorrents(current.getId(), 10);

        return similarTorrents.stream()
                .map(entry -> {
                    Long torrentId = (Long) entry.get("similarTorrentId");
                    return torrentService.getTorrentById(torrentId);
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }
//    public List<Torrent> recommendByUserCF(Long userId) {
//        // 1. 获取相似用户
//        List<UserSimilarity> similarities = userBehaviorMapper.findSimilaritiesByUser(userId);
//
//        // 2. 获取当前用户的行为记录
//        Set<Long> userTorrents = userBehaviorMapper.findByUserId(userId).stream()
//                .map(UserBehavior::getTorrentId)
//                .collect(Collectors.toSet());
//
//        // 3. 收集相似用户喜欢的种子
//        Map<Long, Double> candidateTorrents = new HashMap<>();
//        for (UserSimilarity similarity : similarities) {
//            Long similarUserId = similarity.getUserId1().equals(userId) ?
//                    similarity.getUserId2() : similarity.getUserId1();
//
//            List<UserBehavior> behaviors = userBehaviorMapper.findByUserId(similarUserId);
//            for (UserBehavior behavior : behaviors) {
//                Long torrentId = behavior.getTorrentId();
//                if (!userTorrents.contains(torrentId)) {
//                    candidateTorrents.put(torrentId,
//                            candidateTorrents.getOrDefault(torrentId, 0.0) + similarity.getSimilarity());
//                }
//            }
//        }
//
//        // 4. 按相似度排序并获取种子详情
//        return candidateTorrents.entrySet().stream()
//                .sorted(Map.Entry.<Long, Double>comparingByValue().reversed())
//                .limit(20)
//                .map(entry -> torrentService.getTorrentById(entry.getKey()))
//                .filter(Objects::nonNull)
//                .collect(Collectors.toList());
//    }

    // 基于协同过滤的种子相关推荐
//    public List<Torrent> recommendRelatedTorrentsCF(String infoHash) {
//        // 1. 获取当前种子
//        Torrent current = torrentService.getTorrentByHash(infoHash);
//        if (current == null) return Collections.emptyList();
//
//        // 2. 从数据库获取相似种子
//        List<Map<String, Object>> similarTorrents = torrentSimilarityMapper
//                .findSimilarTorrents(current.getId(), 10);
//
//        // 3. 转换为种子列表
//        return similarTorrents.stream()
//                .map(entry -> {
//                    Long torrentId = (Long) entry.get("similarTorrentId");
//                    return torrentService.getTorrentById(torrentId);
//                })
//                .filter(Objects::nonNull)
//                .collect(Collectors.toList());
//    }

//    // 修改原有的相关推荐方法，结合协同过滤
//    public List<Torrent> recommendRelatedTorrents(String infoHash) {
//        // 先尝试协同过滤推荐
//        List<Torrent> cfRecommendations = recommendRelatedTorrentsCF(infoHash);
//        if (!cfRecommendations.isEmpty()) {
//            return cfRecommendations;
//        }
//
//        // 协同过滤无结果时回退到基于标签的推荐
//        Torrent current = torrentService.getTorrentByHash(infoHash);
//        if (current == null || current.getTags() == null) return Collections.emptyList();
//
//        String[] tags = current.getTags().split(",");
//        return Arrays.stream(tags)
//                .flatMap(tag -> torrentMapper.searchByTag(tag, "seeders", "DESC", 10, 0).stream())
//                .filter(t -> !t.getInfoHash().equals(infoHash))
//                .distinct()
//                .limit(10)
//                .collect(Collectors.toList());
//    }
//
//    // 基于用户行为推荐（最近浏览/下载的资源的标签）
//    public List<Torrent> recommendByUserBehavior(Long userId) {
//        // 获取用户最近的50条行为记录
//        List<UserBehavior> behaviors = userBehaviorMapper.findRecentByUser(userId, 50);
//
//        // 提取所有关联资源的标签
//        Set<String> tags = behaviors.stream()
//                .filter(behavior -> behavior != null && behavior.getTorrent() != null)
//                .map(behavior -> behavior.getTorrent().getId()) // 通过关联对象获取 ID
//                .map(torrentService::getTorrentById)
//                .filter(torrent -> torrent != null && torrent.getTags() != null)
//                .flatMap(torrent -> Arrays.stream(torrent.getTags().split(",")))
//                .collect(Collectors.toSet());
//
//        // 根据标签查询资源（按下载量排序）
//        return tags.stream()
//                .flatMap(tag -> torrentMapper.searchByTag(tag, "download_count", "DESC", 20, 0).stream())
//                .distinct()
//                .limit(20)
//                .collect(Collectors.toList());
//    }
//
//    // 基于用户兴趣标签推荐
//    public List<Torrent> recommendByUserInterest(Long userId) {
//        // 获取用户兴趣标签
//        List<UserInterest> interests = userInterestMapper.findByUserId(userId);
//        Set<String> tags = interests.stream()
//                .map(UserInterest::getTag)
//                .collect(Collectors.toSet());
//
//        // 根据标签查询资源（按创建时间排序）
//        return tags.stream()
//                .flatMap(tag -> torrentMapper.searchByTag(tag, "create_time", "DESC", 20, 0).stream())
//                .distinct()
//                .limit(20)
//                .collect(Collectors.toList());
//    }

    // 热门下载（按下载次数排序）
    public List<TorrentResponse> getHotTorrents() {
        return torrentMapper.findTopDownloaded(20).stream()
                .map(torrent -> {
                    String coverImageBase64 = null;
                    if (torrent.getCoverImage() != null) {
                        coverImageBase64 = torrentService.convertImageToBase64(torrent.getCoverImage());
                    }
                    return new TorrentResponse(torrent, coverImageBase64);
                })
                .collect(Collectors.toList());
    }

    // 最新上传
    public List<TorrentResponse> getLatestTorrents() {
        return torrentMapper.findLatest(20).stream()
                .map(torrent -> {
                    String coverImageBase64 = null;
                    if (torrent.getCoverImage() != null) {
                        coverImageBase64 = torrentService.convertImageToBase64(torrent.getCoverImage());
                    }
                    return new TorrentResponse(torrent, coverImageBase64);
                })
                .collect(Collectors.toList());
    }

    // 相关资源推荐
//    public List<Torrent> recommendRelatedTorrents(String infoHash) {
//        Torrent current = torrentService.getTorrentByHash(infoHash);
//        if (current == null || current.getTags() == null) return Collections.emptyList();
//
//        // 提取当前资源的标签
//        String[] tags = current.getTags().split(",");
//        return Arrays.stream(tags)
//                .flatMap(tag -> torrentMapper.searchByTag(tag, "seeders", "DESC", 10, 0).stream())
//                .filter(t -> !t.getInfoHash().equals(infoHash))
//                .distinct()
//                .limit(10)
//                .collect(Collectors.toList());
//    }
}